package org.ciallo.simplemusicplayer.data.dao;

import androidx.lifecycle.LiveData;
import androidx.room.*;
import org.ciallo.simplemusicplayer.data.model.Playlist;
import org.ciallo.simplemusicplayer.data.model.PlaylistSongCrossRef;
import org.ciallo.simplemusicplayer.data.model.Song;

import java.util.List;

/**
 * @author Jukomu
 * @Description: Playlist 及相关操作的数据访问对象 (DAO)
 * @Package: org.ciallo.simplemusicplayer.data.dao
 * @Project: SimpleMusicPlayer
 * @name: PlaylistDao
 * @Date: 2025/5/30-00:58
 * @Filename: PlaylistDao
 */
@Dao
public interface PlaylistDao {

    /**
     * 插入一个新的歌单。如果冲突，则替换。
     * @param playlist 要插入的歌单对象。
     * @return 新插入歌单的行ID (即 playlist.id)。
     */
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    long insertPlaylist(Playlist playlist);

    /**
     * 更新一个已存在的歌单信息 (例如名称、描述、封面)。
     * @param playlist 要更新的歌单对象。
     */
    @Update
    void updatePlaylist(Playlist playlist);

    /**
     * 删除一个歌单。
     * 由于外键设置了级联删除，相关的 PlaylistSongCrossRef 记录也会被删除。
     * @param playlist 要删除的歌单对象。
     */
    @Delete
    void deletePlaylist(Playlist playlist);

    /**
     * 根据ID获取一个歌单的详细信息。
     * @param playlistId 歌单ID。
     * @return LiveData 包装的歌单对象。
     */
    @Query("SELECT * FROM playlists WHERE id = :playlistId LIMIT 1")
    LiveData<Playlist> getPlaylistById(long playlistId);

    /**
     * 获取所有歌单，按创建日期降序排列。
     * @return LiveData 包装的歌单列表。
     */
    @Query("SELECT * FROM playlists ORDER BY creation_date DESC")
    LiveData<List<Playlist>> getAllPlaylists();

    /**
     * 将一首歌曲添加到指定的歌单中。
     * @param crossRef PlaylistSongCrossRef 对象，包含歌单ID、歌曲ID和位置。
     */
    @Insert(onConflict = OnConflictStrategy.IGNORE) // 如果歌曲已在歌单中，忽略重复添加
    void addSongToPlaylist(PlaylistSongCrossRef crossRef);

    /**
     * 从指定的歌单中移除一首歌曲。
     * @param playlistId 歌单ID。
     * @param songId     歌曲ID。
     */
    @Query("DELETE FROM playlist_song_cross_ref WHERE playlist_id = :playlistId AND song_id = :songId")
    void removeSongFromPlaylist(long playlistId, long songId);

    /**
     * 获取指定歌单中的所有歌曲，并按它们在歌单中的位置排序。
     * 这是一个事务性查询，因为它涉及到两个表的联接。
     * @param playlistId 歌单ID。
     * @return LiveData 包装的该歌单中的歌曲列表 (Song对象)。
     */
    @Transaction // 保证原子性
    @Query("SELECT s.* FROM songs s " +
            "INNER JOIN playlist_song_cross_ref ps_ref ON s.id = ps_ref.song_id " +
            "WHERE ps_ref.playlist_id = :playlistId " +
            "ORDER BY ps_ref.position_in_playlist ASC")
    LiveData<List<Song>> getSongsForPlaylistOrdered(long playlistId);

    /**
     * 更新指定歌单的歌曲数量。
     * @param playlistId 歌单ID。
     * @param newSongCount 新的歌曲数量。
     */
    @Query("UPDATE playlists SET song_count = :newSongCount WHERE id = :playlistId")
    void updatePlaylistSongCount(long playlistId, int newSongCount);


    /**
     * 获取指定歌单中，下一首可用的歌曲位置 (用于添加新歌时)。
     * @param playlistId 歌单ID。
     * @return 下一个可用的位置索引 (从0开始)。
     */
    @Query("SELECT COALESCE(MAX(position_in_playlist), -1) + 1 FROM playlist_song_cross_ref WHERE playlist_id = :playlistId")
    int getNextPositionInPlaylist(long playlistId);

    /**
     * 更新指定歌单的歌曲数量。
     * 这个方法由 Repository 在添加或删除歌曲后调用。
     * @param playlistId 歌单ID。
     */
    @Query("UPDATE playlists SET song_count = (SELECT COUNT(DISTINCT song_id) FROM playlist_song_cross_ref WHERE playlist_id = :playlistId) WHERE id = :playlistId")
    void updatePlaylistSongCountAfterModification(long playlistId);

    /**
     * DTO 用于从数据库查询歌单及其第一首歌的封面URI。
     */
    class PlaylistDetailQueryResult {
        // 从 Playlist 表中选择所有字段
        @ColumnInfo(name = "id") public long id;
        @ColumnInfo(name = "name") public String name;
        @ColumnInfo(name = "description") public String description;
        @ColumnInfo(name = "creation_date") public long creationDate;
        @ColumnInfo(name = "song_count") public int songCount;

        // 额外查询的字段：该歌单第一首歌的专辑封面URI
        @ColumnInfo(name = "first_song_cover_uri")
        public String firstSongCoverUri;
    }

    /**
     * 获取所有歌单，并附带每个歌单第一首歌的封面URI，按创建日期降序排列。
     *
     * @return LiveData 包装的 PlaylistDetailQueryResult 列表。
     */
    @Query("SELECT p.id, p.name, p.description, p.creation_date, p.song_count, " +
            "(SELECT s.album_art_uri FROM songs s " +
            "INNER JOIN playlist_song_cross_ref psr ON s.id = psr.song_id " +
            "WHERE psr.playlist_id = p.id ORDER BY psr.position_in_playlist ASC LIMIT 1) as first_song_cover_uri " +
            "FROM playlists p ORDER BY p.creation_date DESC")
    LiveData<List<PlaylistDetailQueryResult>> getAllPlaylistsWithFirstSongCover(); // <--- 修改方法名和返回类型


    /**
     * 根据歌单名称搜索歌单，按创建日期降序排列。
     * 如果查询词为 null 或空，则返回所有歌单。
     *
     * @param query (可选) 包含 '%'通配符的歌单名称搜索查询词。
     * @return LiveData 包装的歌单列表。
     */
    @Query("SELECT * FROM playlists WHERE " +
            "(:query IS NULL OR :query = '' OR name LIKE :query) " +
            "ORDER BY creation_date DESC")
    LiveData<List<Playlist>> getAllPlaylistsOrSearchByName(String query);
}